#include "databasequery.h"
#include "database/database.h"
#include <QStringList>
#include "common/tdebug.h"
#include <QSqlError>
#include <QMessageBox>
#include <QMap>
//#include "mymessagedialog.h"


SignReceiver* SignReceiver::mObj = 0;


QString DataBaseQuery::indexName(const QString &name)
{
    return "index_" + name;
}

DataBaseQuery::DataBaseQuery(QSqlDatabase db,bool showErr):QSqlQuery(db)
{
    mSignSender = new SignSender(0);
    if(showErr){
        QObject::connect(mSignSender,SIGNAL(error(QString,QString)),SignReceiver::getObj(),SLOT(showError(QString,QString)));
    }
}

void DataBaseQuery::setErrHandleSlot(const QObject *receiver,const char *member)
{
    QObject::connect(mSignSender,SIGNAL(error(QString,QString)),receiver,member);
}

DataBaseQuery::~DataBaseQuery()
{
    delete mSignSender;
}

bool DataBaseQuery::containColumn(const QString &tabName,const QString &column)
{
    QString str = "select * from "+ tabName +" where " + column +"= txdfasf";
    //tDebug()<<str;
    return exec(str);
}


bool DataBaseQuery::addColumn(const QString &tabName,const QString &column,const QString &option)
{
    QString str = "ALTER TABLE "+ tabName +" ADD " + column +" "+option;
     //tDebug()<<str;
    return exec(str);
}


/*
void DataBaseQuery::insert(QString tabName,QList<DataBaseData> &dataList)//Q<QString >//const QStringList *keyList,QVariantList *valueList)
{
    QString str = "insert into " +tabName + " (";
    QString valueStr = "values (";

    int i;
    for(i=0;i<dataList.count()-1;i++)
    {
        str+=dataList.at(i).mStrName;
        str+=',';

        valueStr += "?";
        valueStr += ',';
    }
    str+=dataList.at(i).mStrName;
    str+=") ";
    valueStr += "?";
    valueStr += ')';
    str+=valueStr;
    prepare(str);
    //////tDebug()<<str;
    for(i=0;i<dataList.count();i++)
    {
        addBindValue(dataList.at(i).mContent);
    }
    if(exec()==0)
    {
        //////tDebug()<<lastError();
    }


}
*/
bool DataBaseQuery::resetAllTable()
{
    QStringList list = DataBase::getDataBase().tables();
    list.removeOne("sqlite_sequence");
    //tDebug()<<list;
    for(int i =0,t=list.count();i<t;i++)
    {
        resetTable(list.at(i));
    }
}


bool DataBaseQuery::resetTable(const QString &tabName)
{
    return exec("delete  from " + tabName);
}

bool DataBaseQuery::deleteTable(const QString &tabName)
{
    return exec("DROP  TABLE " + tabName);
}

bool DataBaseQuery::createIndex(const QString &tabName, const QString &fieldName, const QString &indexName)
{\
    QString indexStr = indexName;
    if(indexStr == "")
        indexStr = DataBaseQuery::indexName(fieldName);

    QString str = "create index if not exists " +
                indexStr + " on " + tabName +"(" +
                fieldName + ")";
   return exec(str);
}



bool DataBaseQuery::exec(const QString &str)
{
    if(QSqlQuery::exec(str)==false){
        //if(mShowErr){
            mSignSender->sendErrorSignal(QObject::tr("DataBase Error"),str+lastError().databaseText()+'\n'+lastError().driverText());
       // }
        return false;
    } else
        return true;
}

bool DataBaseQuery::exec()
{
    if(QSqlQuery::exec()==false){
       // if(mShowErr){
            mSignSender->sendErrorSignal(QObject::tr("DataBase Error"),lastQuery()+'\n' + lastError().databaseText()+'\n'+lastError().driverText());
       // }
        return false;
    } else
        return true;
}

void DataBaseQuery::getDataFromTable(const QString &tabName,QList< QMap<QString,QVariant> > *list)
{
    if(list==NULL) return;

    DataBaseQuery query;
    QString str = "select DISTINCT ";
    str+=" * from ";
    str+=tabName;
    if(query.exec(str))
    {
        while(query.next())
        {
            QSqlRecord rcd = query.record();
            QMap<QString,QVariant> map;// = new QMap<QString,QVariant>;
            for(int i =0;i<rcd.count();i++)
            {
                map.insert(rcd.fieldName(i),rcd.value(i));
            }
            list->append(map);
        }
    }
}

void DataBaseQuery::copy(const QString &tabName,DataBaseQuery *qyDest,const DataBaseQuery *qySource)
{
    QSqlRecord rcd = qySource->record();
    QMap<QString,QVariant> map;
    for(int i =0;i<rcd.count();i++)
    {
        map.insert(rcd.fieldName(i),rcd.value(i));

    }
    qyDest->insert(tabName,map);

}
void DataBaseQuery::copy(const QString &dest, const QString &src, const QString &option)
{
    QString str = "insert into " + dest + " select * from "+ src;
    if(option.isEmpty()==false){
        str += " where " + option;
    }
    this->exec(str);
}

void DataBaseQuery::move(const QString &dest, const QString &src, const QString &option)
{
    copy(dest,src,option);
    deleteItem(src,option);
}

bool DataBaseQuery::insert(const QString &tabName,const QList< QMap<QString,QVariant> > *list)
{
    if(list==0) return false;
    for(int loop=0,t=list->count();loop<t;loop++)
    {
        QMap<QString,QVariant> dataMap = list->at(loop);
        insert(tabName,dataMap);
    }
    return true;
}


bool DataBaseQuery::insert(const QString &tabName,const QMap<QString,QVariant> &dataMap)//Q<QString >//const QStringList *keyList,QVariantList *valueList)
{
    QString str = "insert into " +tabName + " (";
    QString valueStr = "values (";

    int i;
    QStringList keyList = dataMap.keys();//dataList.keys();
    QVariantList valueList = dataMap.values();
    for(i=0;i<keyList.count()-1;i++)
    {
        str+=keyList.at(i);
        str+=',';
        valueStr += "?";
        valueStr += ',';
    }
    str+=keyList.at(i);
    str+=") ";
    valueStr += "?";
    valueStr += ')';
    str+=valueStr;
    prepare(str);
    
    for(i=0;i<keyList.count();i++)
    {
        addBindValue(valueList.at(i));
    }
    return exec();
}


/*

bool DataBaseQuery::selectTable(QString tabName,const QStringList *keyList, const QMap<QString,QVariant>*where,QString shortItem,bool shortdesc)
{
    QString str = "select DISTINCT ";
    if(keyList==NULL)
    {
        str+="* ";
    }
    else
    {
        int i = 0;
        for(i=0;i<keyList->count()-1;i++)
        {
            str+=keyList->at(i);
            str+=',';
        }
        str+=keyList->at(i);

    }
    str+=" from ";
    str+=tabName;

    if(where!=NULL)
    {
        str+=" where ";
        QStringList keyList = where->keys();//dataList.keys();
        QVariantList valueList = where->values();
        for(int i=0;i<keyList.count();i++)
        {
            str+=keyList.at(i);
            str+='=';
            str+='?';
        }
        prepare(str);
        //////tDebug()<<str;
        for(int i=0;i<keyList.count();i++)
        {
            addBindValue(valueList.at(i));
        }
    }

    if(shortItem.length()!=0)
    {
        str+=" short by ";
        str+=shortItem;
        if(shortdesc)
        {
            str+= " desc";
        }
        else
        {
            str+= " asc";
        }
    }

    if(exec()==false)
    {
        QMessageBox::critical(NULL,"Error",
                           lastError().databaseText()
                           +'\n'
                           +lastError().driverText());
        //////tDebug()<<lastError();
        return false;
    }

    return true;
}*/
bool DataBaseQuery::innerJoin(QString tabName, const QStringList *keyList, const QStringList &joinOption)
{
    QString str = "select DISTINCT";
    if(keyList==NULL)
    {
        str+="* ";
    }
    else
    {
        int i = 0;
        for(i=0;i<keyList->count()-1;i++)
        {
            str+=keyList->at(i);
            str+=',';
        }
        str+=keyList->at(i);
    }
    str+=" from ";
    str+=tabName;
    for(int i =0; i<joinOption.count();i++)
    {
        str+= " INNER JOIN ";
        str+= joinOption.at(i);
    }

    return exec(str);
}

bool DataBaseQuery::innerJoin(const QString &tabName,
                              const QStringList *itemList,
                              QMap<QString, QString> &joinOption,
                              const QString &option,
                              const QString &order
                              )
{
    QString str = "select DISTINCT ";
    if(itemList==NULL)
    {
        str+="* ";
    }
    else
    {
        int t =itemList->count();
        if(t>0)
            str += itemList->join(",");
         else
            str += "* ";
    }
    str+=" from ";
    str+=tabName;
    QStringList keyList = joinOption.keys();
    QStringList valueList = joinOption.values();
    for(int i =0,t = joinOption.count();  i<t;  i++)
    {
        str+= " INNER JOIN ";
        str+= keyList.at(i);
        str+= " on ";
        str+= valueList.at(i);
    }

    if(option!="")
    {
        str += " ";
        if(!option.startsWith("where",Qt::CaseInsensitive))
        {
            str += "where ";
        }
        str +=option;
    }

    if(order.length()!=0)
    {
        str+=" order by  " + order;
    }
    //tDebug()<<str;
    return exec(str);
}


bool DataBaseQuery::leftJoin(const QString &tabName,
                              const QStringList *itemList,
                              QMap<QString, QString> &joinOption,
                              const QString &option,
                              const QString &order
                              )
{
    QString str = "select DISTINCT ";
    if(itemList==NULL)
    {
        str+="* ";
    }
    else
    {
        int t =itemList->count();
        if(t>0)
            str += itemList->join(",");
         else
            str += "* ";
    }
    str+=" from ";
    str+=tabName;
    QStringList keyList = joinOption.keys();
    QStringList valueList = joinOption.values();
    for(int i =0,t = joinOption.count();  i<t;  i++)
    {
        str+= " LEFT JOIN ";
        str+= keyList.at(i);
        str+= " on ";
        str+= valueList.at(i);
    }

    if(option!="")
    {
        str += " ";
        if(!option.startsWith("where",Qt::CaseInsensitive))
        {
            str += "where ";
        }
        str +=option;
    }

    if(order.length()!=0)
    {
        str+=" order by  " + order;
    }
    //tDebug()<<str;
    return exec(str);
}

bool DataBaseQuery::leftJoin(const QString &tabName1, const QString &tabName2, const QStringList *keyList,const QString &option)
{


    QString str = "select DISTINCT ";
    if(keyList==NULL)
    {
        str+="* ";
    }
    else
    {
        int i = 0;
        for(i=0;i<keyList->count()-1;i++)
        {
            str+=keyList->at(i);
            str+=',';
        }
        str+=keyList->at(i);
    }
    str+=" from ";
    str+=tabName1;
    str+=" left join ";
    str+=tabName2;


    if(option.length()!=0)
    {
        str+=" on ";
        str+=option;
    }

    //////tDebug()<<str;
    return exec(str);
}

bool DataBaseQuery::selectTable(const QString &tabName,
                                const QStringList *keyList,
                                const QString &option,
                                const QString &shortItem,bool shortdesc)
{
    QString str = "select DISTINCT ";
    if(keyList==NULL)
    {
        str+="* ";
    }
    else
    {
        int i = 0;
        int t = keyList->count();
        if(t!=0)
        {
            for(i=0;i<t-1;i++)
            {
                str+=keyList->at(i);
                str+=',';
            }
            str+=keyList->at(i);
        }
        else
        {
            str+="* ";
        }

    }
    str+=" from ";
    str+=tabName;

    if(option.length()!=0){
        QString opt = option.trimmed();

        if(opt.startsWith("where")){
            str+=" " +opt;
        }
        else if(opt.startsWith("limit")){
             str+=" " +opt;
        }
        else
            str+=" where " + opt;

    }

    if(shortItem.length()!=0)
    {
        QStringList list=shortItem.split(',');
        int t = list.size();

        str+=" order by  ";
        for(int i=0;i<t-1;i++)
        {
            //str+="UPPER(";
            str+=list.at(i);
            str+=",";
            //str+="),";
        }
       // str+="UPPER(";
        str+=list.at(t-1);
        //str+=")";


        if(shortdesc)
        {
            str+= " desc";
        }
        else
        {
            str+= " asc";
        }
    }
    return exec(str);
}


/*
bool DataBaseQuery::selectTable(const QString &tabName,
                                const QStringList *keyList,
                                const QStringList &optionList,
                                const QString &shortItem,
                                bool shortdesc)
{
    QString str = "select DISTINCT ";
    if(keyList==NULL)
    {
        str+="* ";
    }
    else
    {
        int i = 0;
        int t = keyList->count();
        if(t!=0)
        {
            for(i=0;i<t-1;i++)
            {
                str+=keyList->at(i);
                str+=',';
            }
            str+=keyList->at(i);
        }
        else
        {
            str+="* ";
        }

    }
    str+=" from ";
    str+=tabName;

    if(optionList.count()!=0)
    {
        str += " where " + optionList.join(" and ");
    }

    if(shortItem.length()!=0)
    {
        QStringList list=shortItem.split(',');
        int t = list.size();

        str+=" order by  ";
        for(int i=0;i<t-1;i++)
        {
            //str+="UPPER(";
            str+=list.at(i);
            str+=",";
            //str+="),";
        }
       // str+="UPPER(";
        str+=list.at(t-1);
        //str+=")";


        if(shortdesc)
        {
            str+= " desc";
        }
        else
        {
            str+= " asc";
        }
    }
    return exec(str);
}

*/
bool DataBaseQuery::selectTable(const QStringList *tabList,const QStringList *keyList,const QString &option)
{
    int i;
    QString str = "select DISTINCT ";
    if(tabList==NULL)
        return false;
    if(keyList==NULL)
    {
        str+="* ";
    }
    else
    {
        int t = keyList->count();
        if(t!=0)
        {
            for(i=0;i<t-1;i++)
            {
                str+=keyList->at(i);
                str+=',';
            }
            str+=keyList->at(i);
        }
        else
        {
            str+="* ";
        }

    }
    str+=" from ";
    for(i=0;i<tabList->count()-1;i++)
    {
        str+=tabList->at(i);
        str+=',';
    }
    str+=tabList->at(i);
    if(option.length()!=0)
        str+=" where " +option;
    return exec(str);
}

//bool DataBaseQuery::selectTable(const QString &tab, const QString &key, const QString &content, const QStringList *keyList)
//{
//    selectTable(tab,keyList,"content")
//}

bool DataBaseQuery::deleteItem(const QString &tabName,const QString &option)
{
    QString str = "DELETE";
    str+=" from ";
    str+= tabName;
    if(option.length()!=0)
        str+=" where " +option;
    return exec(str);
}



bool DataBaseQuery::deleteItem(const QString &tabName, const QString &key,const QVariant &dat)
{
    QString str = "DELETE";
    str+=" from ";
    str+= tabName;
    str+=" where " + key + "=";
    str+="?";
    prepare(str);
    ////tDebug()<<str;

    addBindValue(dat);
    return exec();
}


bool DataBaseQuery::deleteItem(const QString &tabName, const QMap<QString,QVariant> &dataMap)
{
    QString str = "DELETE";
    str+=" from ";
    str+= tabName;
    str+=" where ";
    QStringList keyList = dataMap.keys();//dataList.keys();
    QVariantList valueList = dataMap.values();//dataList.keys();
    int i;
    for(i=0;i<keyList.count()-1;i++)
    {
        str += keyList.at(i);
        str += " = ";
        str += "?";
        str += " AND ";
    }
    str += keyList.at(i);
    str += "=";
    str += "?";
    prepare(str);
    ////tDebug()<<str;
    for(i=0;i<keyList.count();i++)
    {
        addBindValue(valueList.at(i));
    }

    return exec();
}

bool DataBaseQuery::updateItem(const QString &tabName,const QMap<QString,QString> &dataMap,const QString &option)
{
    QString str = "update " +tabName + " SET ";
    QStringList keyList = dataMap.keys();//dataList.keys();
    QStringList valueList = dataMap.values();//dataList.keys();
    for(int i=0,t=keyList.count(); i<t; i++)
    {
        str+=keyList.at(i);
        str+='=';
        str += valueList.at(i);
        str += ',';
    }
    str.chop(1);
    if(option.length()!=0)
        str+=" where " + option;
    tDebug()<<str;
    return exec(str);
}



bool DataBaseQuery::updateItem(const QString &tabName,
                               const QString &fieldName,
                               const QString &now,
                               const QMap<QString, QVariant> &dataMap_new)
{
    QString str="UPDATE "+tabName+" SET ";
    int i;
    QStringList keyList = dataMap_new.keys();//dataList.keys();
    QVariantList valueList = dataMap_new.values();//dataList.keys();
    for(i=0;i<keyList.count()-1;i++)
    {
        str+=keyList.at(i);
        str+='=';
        str += "?";
        str += ',';
    }
    str+=keyList.at(i);
    str+="=";
    str += "?";
    if(now.count()!=0)
        str+=" WHERE "+fieldName+" = "+"\""+now+"\"";
    DDDValue(str);
    prepare(str);

    for(i=0;i<keyList.count();i++)
    {
        addBindValue(valueList.at(i));
        qDebug()<<(valueList.at(i).toString());
    }
    DDDValue(str);
    return exec();
}


bool DataBaseQuery::isItemExist(const QString &tabName,const QString &item,const QVariant &content)
{
    QString str = "select DISTINCT ";
    str+=item;
    str+=" from ";

    str+=tabName;
    str+=" where "+ item + "=?";
    prepare(str);
    addBindValue(content);

    if(exec()==0){
        return false;
    }
    if(this->first())
        return true;
    return false;
}

bool DataBaseQuery::updateItem(const QString &tabName,const QMap<QString,QVariant> &dataMap,const QString &option)
{
    QString str = "update " +tabName + " SET ";
    int i;
    QStringList keyList = dataMap.keys();//dataList.keys();
    QVariantList valueList = dataMap.values();//dataList.keys();
    for(i=0;i<keyList.count()-1;i++)
    {
        str+=keyList.at(i);
        str+='=';
        str += "?";
        str += ',';
    }
    str+=keyList.at(i);
    str+="=";
    str += "?";
    if(option.length()!=0)
        str+=" where " +option;
    prepare(str);

    ////tDebug()<<str;
    for(i=0;i<keyList.count();i++)
    {
        addBindValue(valueList.at(i));
        //////tDebug()<<"1";
    }
    return exec();
}


bool DataBaseQuery::copyTab(const QString &destTab, const QString &srcTab)
{


    QString str = "insert into " +destTab ;
    str+=" select * from ";
    str+=srcTab;

    return exec(str);
}

int DataBaseQuery::size()
{
    if(last())
    {
        return at()+1;
    }
    return 0;
}

